package com.fastloan.mgt.application.base.service.impl;

import com.alibaba.fastjson.JSON;
import com.fastloan.common.BasicServiceImpl;
import com.fastloan.common.model.CheckResult;
import com.fastloan.mgt.application.base.dao.ApplicationValueMapper;
import com.fastloan.mgt.application.base.dao.ApplicationValueModifyHistoryMapper;
import com.fastloan.mgt.application.base.model.*;
import com.fastloan.mgt.application.base.service.ApplicationIPCService;
import com.fastloan.mgt.application.base.service.ApplicationService;
import com.fastloan.mgt.jx.model.dto.JxApplicationStateDTO;
import com.fastloan.safe.core.util.ManagerKit;
import com.kawins.supers.file.core.FileLoadBean;
import com.kawins.supers.tree.Bean2TreeUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.util.*;

import java.util.function.BiConsumer;

import static java.util.stream.Collectors.toList;


/**
 * @author yanwe
 * createTime 2017-11-2017/11/8 13:39
 */
@Service
public class ApplicationIPCServiceImpl extends BasicServiceImpl<ApplicationValue> implements ApplicationIPCService {

    @Autowired
    private ApplicationValueMapper applicationValueMapper;

    @Autowired
    private ApplicationValueModifyHistoryMapper applicationValueModifyHistoryMapper;

    @Autowired
    private ApplicationService applicationService;

    @Override
    public List<ApplicationIPC> selectApplicationIPCNoTree(String applicationId) {
        List<ApplicationIPC> currentApplicationIPCS = applicationValueMapper.selectApplicationIPC(applicationId);
        Application application = applicationService.selectByPrimaryKey(applicationId);
        setLastApplicationIPCInfo(application.getCustomerId(),currentApplicationIPCS);//保存上次IPC信息
        return currentApplicationIPCS;
    }

    @Override
    public List<ApplicationIPC> selectApplicationIPC(String applicationId) {
        Bean2TreeUtil<ApplicationIPC> treeUtil = new Bean2TreeUtil<>();
        return treeUtil.getChildNodesByParentId(selectApplicationIPCNoTree(applicationId), 0);
    }

    @Override
    public List<ApplicationIPC> selectApplicationIPC(String applicationId, Integer type) {
        List<ApplicationIPC> applicationIPCS = selectApplicationIPC(applicationId);
        filterType(applicationIPCS,type);
        return applicationIPCS;
    }

    @Override
    public List<ApplicationIPC> selectProductIPC(String productId, Integer type,String customerId) {
        return selectProductIPC(productId,type,customerId,this::setLastApplicationIPCInfo);
    }

    @Override
    public List<ApplicationIPC> selectProductIPC(String productId, Integer type) {
        return selectProductIPC(productId,type,null,null);
    }

    @Override
    public boolean addIPC(List<ApplicationValue> applicationValueList) {
        return applicationValueMapper.insertList(applicationValueList) == applicationValueList.size();
    }

    @Override
    @Transactional
    public CheckResult updateIPC(ApplicationValue applicationValue, String remark) {
        ApplicationValue beforeIPC = applicationValueMapper
                .selectByPrimaryKey(applicationValue.getApplicationIpcId());
        if (beforeIPC == null) {
            return CheckResult.fail("需要更改的IPC不存在：" + applicationValue);
        }
        ApplicationValueModifyHistory applicationValueModifyHistory = new ApplicationValueModifyHistory();
        applicationValueModifyHistory.setBeforeValue(beforeIPC.getApplicationValue());
        applicationValueModifyHistory.setAfterValue(applicationValue.getApplicationValue());
        if (applicationValueModifyHistory.getAfterValue()
                .equals(applicationValueModifyHistory.getBeforeValue())) {
            return CheckResult.fail("不能修改同样的值！");
        }
        applicationValueModifyHistory.setApplicationIpcId(applicationValue.getApplicationIpcId());
        applicationValueModifyHistory.setRemark(remark);
        applicationValueModifyHistory.setModifyTime(new Date());
        applicationValueModifyHistory.setModifyUserId(ManagerKit.getUserId());
        applicationValueModifyHistory.setRoleId(String.valueOf(ManagerKit.getRole().getIndexType()));
        int applicationValueResult = updateByPrimaryKeySelective(applicationValue);
        int historyResult = applicationValueModifyHistoryMapper.insertSelective(applicationValueModifyHistory);
        return (applicationValueResult + historyResult) == 2 ? CheckResult.success() : CheckResult.fail("修改失败！");
    }

    @Override
    @Transactional
    public ApplicationValue uploadIPCFile(String applicationIpcId, MultipartFile[] files) {
        List<FileLoadBean> fileLoadBeanList = fileManager.upload(files);
        ApplicationValue applicationValue = applicationValueMapper.selectByPrimaryKey(applicationIpcId);
        List<IpcFile> ipcFiles = JSON.parseArray(applicationValue.getApplicationValue(), IpcFile.class);
        if (ipcFiles == null) {
            ipcFiles = new ArrayList<>();
        }
        List<IpcFile> newIpcFiles = fileLoadBeanList.stream()
                .map(fileLoadBean -> new IpcFile(fileLoadBean.getFileId().toString(), fileLoadBean.getFileName()
                        , fileLoadBean.getFileServer() + fileLoadBean.getGroupName() + "/" + fileLoadBean.getRemoteFileName()))
                .collect(toList());
        ipcFiles.addAll(newIpcFiles);
        applicationValue.setApplicationValue(JSON.toJSONString(ipcFiles));
        applicationValueMapper.updateByPrimaryKey(applicationValue);
        return applicationValue;
    }

    @Override
    @Transactional
    public ApplicationValue deleteFile(String applicationIpcId, String fileId) {
        ApplicationValue applicationValue = applicationValueMapper.selectByPrimaryKey(applicationIpcId);
        List<IpcFile> ipcFiles = JSON.parseArray(applicationValue.getApplicationValue(), IpcFile.class);
        ipcFiles.removeIf(ipcFile -> ipcFile.getFileId().equals(fileId));
        applicationValue.setApplicationValue(JSON.toJSONString(ipcFiles));
        applicationValueMapper.updateByPrimaryKey(applicationValue);
        fileManager.delete(fileId);
        return applicationValue;
    }

    @Override
    public Map<String, List<String>> queryFileIds(String applicationId) {
        List<ApplicationIPC> applicationIPCS = applicationValueMapper.selectApplicationIPC(applicationId);
        Map<String, List<String>> map = new HashMap<>();
        applicationIPCS.stream()
                .filter(applicationIPC -> applicationIPC.getType() != null && (applicationIPC.getType().equals(0) || applicationIPC.getType().equals(1)))
                .filter(applicationIPC -> applicationIPC.getInputType().equals(6) || applicationIPC.getInputType().equals(7))
                .forEach(applicationIPC -> {
                    List<IpcFile> ipcFileList = JSON.parseArray(applicationIPC.getApplicationValue(), IpcFile.class);
                    List<String> stringList = ipcFileList.stream().map(IpcFile::getFileId).collect(toList());
                    String dir = "客户经理";
                    if (applicationIPC.getType() == 0) {
                        dir = "客户";
                    }
                    map.put(dir + File.separator + applicationIPC.getName(), stringList);
                });

        return map;
    }

    private List<ApplicationIPC> selectProductIPC(String productId, Integer type,String customerId
            , BiConsumer<String,List<ApplicationIPC>> setLastIPC) {
        List<ApplicationIPC> productIPC = applicationValueMapper.selectProductIPC(productId);
        if (setLastIPC != null){
            setLastIPC.accept(customerId,productIPC);
        }
        Bean2TreeUtil<ApplicationIPC> treeUtil = new Bean2TreeUtil<>();
        List<ApplicationIPC> treeIPC = treeUtil.getChildNodesByParentId(productIPC, 0);
        filterType(treeIPC,type);//根据类型过滤
        return treeIPC;
    }

    private void setLastApplicationIPCInfo(String customerId,List<ApplicationIPC> currentIPC){
        String lastApplicationId = getLastApplication(customerId)
                .map(Application::getApplicationId).orElse(null);
        List<ApplicationIPC> lastApplicationIpc = applicationValueMapper.selectApplicationIPC(lastApplicationId);
        setLastInfo(currentIPC,lastApplicationIpc);
    }

    private void filterType(List<ApplicationIPC> productIPC, Integer type) {
        Iterator<ApplicationIPC> iterator = productIPC.iterator();
        while (iterator.hasNext()) {
            ApplicationIPC applicationIPC = iterator.next();
            List<ApplicationIPC> childList = applicationIPC.getChildList();
            if (childList == null || childList.isEmpty()) {
                iterator.remove();
                continue;
            }
            childList.removeIf(removeIPC -> !removeIPC.getType().equals(type));
            if (childList.isEmpty()) {
                iterator.remove();
            }
        }
    }

    private void setLastInfo(List<ApplicationIPC> currentApplicationIPCS, List<ApplicationIPC> lastApplicationIPCS) {
        lastApplicationIPCS.forEach(lastApplication -> currentApplicationIPCS.stream()
                .filter(currentApplicationIPC -> currentApplicationIPC.getTempId()
                        .equals(lastApplication.getTempId()))
                .forEach(currentApplicationIPC -> currentApplicationIPC
                        .setLastApplicationValue(lastApplication.getApplicationValue())));
    }

    private Optional<Application> getLastApplication(String customerId) {
        Application criteria = new Application();
        criteria.setCustomerId(customerId);
        return applicationService.select(criteria).stream()
                .sorted(Comparator.comparing(Application::getCreateTime).reversed()).findFirst();
    }

    public static void main(String[] args) {
        JxApplicationStateDTO jxApplicationStateDTO = new JxApplicationStateDTO();
        jxApplicationStateDTO.setAgent_order_id("00ffa2d3-f512-11e7-a908-000c296c31e8");
        jxApplicationStateDTO.setOrder_status(1);
        System.out.println(JSON.toJSONString(jxApplicationStateDTO));
    }

}
